﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security.Cryptography;
using L2Tools.Model;
using L2Tools.L2l2.Properties;

namespace L2Tools.L2l2.View
{
    public partial class L2l2Manager : Form
    {
        #region Enum
        /// <summary>
        /// アプリケーションの動作状態。
        /// </summary>
        enum Status
        {
            Active
            , Passive
            , Error
        }
        #endregion

        #region Const
        /// <summary>
        /// Bytes表示文字列
        /// </summary>
        const string Bytes = " [bytes]";
        /// <summary>
        /// ディレクトリが存在しなかった場合のメッセージ
        /// </summary>
        const string MessageNotExists = "存在しません。";
        #endregion

        #region Attribute
        private readonly L2Directory l2Directory;
        /// <summary>
        /// アプリケーション動作ステータス
        /// </summary>
        private Status status = Status.Passive;
        #endregion

        #region Constructor
        /// <summary>
        /// インスタンスを生成する。
        /// </summary>
        /// <param name="l2Directory"></param>
        internal L2l2Manager()
        {
            InitializeComponent();
            this.l2Directory = new L2Directory(this);
            LoadSettings();
            UpdateViewStatus();
        }
        #endregion

        #region Method
        private void UpdateViewStatus()
        {
            Validation();
            if (l2Directory.L2DirectoryPath != null)
            {
                l2Folder.Text = l2Directory.L2DirectoryPath;
            }
            else
            {
                l2Folder.Text = string.Empty;
            }
            if (l2Directory.RamdiskDirectoryPath != null)
            {
                ramDiskFolder.Text = l2Directory.RamdiskDirectoryPath;
            }
            else
            {
                ramDiskFolder.Text = string.Empty;
            }

            ssFolder.Text = l2Directory.SsRepositoryPath;

            Settings settings = global::L2Tools.L2l2.Properties.Settings.Default;

            checkBoxAnimations.Checked = settings.Animations;
            checkBoxMaps.Checked = settings.Maps;
            checkBoxMusic.Checked = settings.Music;
            checkBoxSounds.Checked = settings.Sounds;
            checkBoxStaticMeshes.Checked = settings.StaticMeshes;
            checkBoxSystem.Checked = settings.System;
            checkBoxSysTextures.Checked = settings.SysTextures;
            checkBoxTextures.Checked = settings.Textures;
            checkBoxVoice.Checked = settings.Voice;

            checkBoxAjustSS.Checked = l2Directory.IsAjust;

            if (l2Directory.Validation())
            {
                ChangeStatus(Status.Passive);
            }
            else
            {
                ChangeStatus(Status.Error);
            }
            CountTotal();
        }

        /// <summary>
        /// 設定状態をチェックする。
        /// </summary>
        private void Validation()
        {
            if (!l2Directory.ValidationL2Directory())
            {
                MessageBox.Show("LineageⅡフォルダを選択してください。");
            }
            if (!l2Directory.ValidationRamdiskDirectory())
            {
                MessageBox.Show("RamDiskフォルダを選択してください。");
            }
            if (!l2Directory.ValidationSsRepository())
            {
                MessageBox.Show("SS保管フォルダを選択してください。");
            }
        }

        private void ChangeStatus(Status status)
        {
            this.status = status;
            switch (this.status)
            {
                case Status.Error:
                    buttonSave.Enabled = true;
                    buttonApply.Enabled = false;
                    buttonTearDown.Enabled = false;
                    buttonStart.Enabled = false;
                    buttonStop.Enabled = false;
                    break;
                case Status.Active:
                    buttonSave.Enabled = true;
                    buttonApply.Enabled = false;
                    buttonTearDown.Enabled = false;
                    buttonStart.Enabled = false;
                    buttonStop.Enabled = true;
                    break;
                case Status.Passive:
                    buttonSave.Enabled = true;
                    buttonApply.Enabled = true;
                    buttonTearDown.Enabled = true;
                    buttonStart.Enabled = true;
                    buttonStop.Enabled = false;
                    break;
            }
        }

        private void ClickSelectL2Directory(object sender, EventArgs e)
        {
            //FolderBrowserDialogクラスのインスタンスを作成
            FolderBrowserDialog fbd = new FolderBrowserDialog();

            //上部に表示する説明テキストを指定する
            fbd.Description = "フォルダを指定してください。";
            //ルートフォルダを指定する
            //デフォルトでDesktop
            fbd.RootFolder = Environment.SpecialFolder.Desktop;
            //最初に選択するフォルダを指定する
            //RootFolder以下にあるフォルダである必要がある
            fbd.SelectedPath = l2Folder.Text;
            //ユーザーが新しいフォルダを作成できるようにする
            //デフォルトでTrue
            fbd.ShowNewFolderButton = false;

            //ダイアログを表示する
            if (fbd.ShowDialog(this) == DialogResult.OK)
            {
                if (!fbd.SelectedPath.Equals(l2Directory.L2DirectoryPath))
                {
                    l2Directory.L2DirectoryPath = fbd.SelectedPath;
                    UpdateViewStatus();
                }
            }
        }

        private void ClickSelectRamDiskDirectory(object sender, EventArgs e)
        {
            //FolderBrowserDialogクラスのインスタンスを作成
            FolderBrowserDialog fbd = new FolderBrowserDialog();

            //上部に表示する説明テキストを指定する
            fbd.Description = "フォルダを指定してください。";
            //ルートフォルダを指定する
            //デフォルトでDesktop
            fbd.RootFolder = Environment.SpecialFolder.Desktop;
            //最初に選択するフォルダを指定する
            //RootFolder以下にあるフォルダである必要がある
            fbd.SelectedPath = ramDiskFolder.Text;
            //ユーザーが新しいフォルダを作成できるようにする
            //デフォルトでTrue
            fbd.ShowNewFolderButton = true;

            //ダイアログを表示する
            if (fbd.ShowDialog(this) == DialogResult.OK)
            {
                if (!fbd.SelectedPath.Equals(l2Directory.RamdiskDirectoryPath))
                {
                    l2Directory.RamdiskDirectoryPath = fbd.SelectedPath;
                    UpdateViewStatus();
                }
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            string l2path = l2Folder.Text;
            if (!Directory.Exists(l2path))
            {
                MessageBox.Show("LineageⅡフォルダを選択してください。");
            }

            string rdPath = ramDiskFolder.Text;
            if (!Directory.Exists(rdPath))
            {
                MessageBox.Show("RamDiskフォルダを選択してください。");
            }

            Apply();
        }

        private void Apply()
        {
            WaitDialog dialog = new WaitDialog();
            dialog.Owner = this;
            dialog.MainMsg = "ファイルのコピー中です";

            L2DirectoryInfo l2DirectoryInfo = l2Directory.Count();

            // ファイル数を設定するように修正すること
            dialog.ProgressMax = l2DirectoryInfo.FileCount;
            dialog.ProgressMin = 0;
            dialog.ProgressValue = 0;
            dialog.ProgressStep = 1;

            this.Enabled = false;
            dialog.Show();

            l2Directory.Setup(new SetupListenerImpl(dialog, l2DirectoryInfo.FileCount));

            // チェックされていないディレクトリをRamDisk上から削除する。
            SaveSettings();

            // 最終メッセージを表示して、閉じるのを少し遅らせる
            if (dialog.DialogResult == DialogResult.Abort)
            {
                dialog.SubMsg = "処理を中断しました。";
            }
            else
            {
                dialog.SubMsg = "処理を完了しました。";
            }

            // いったんオーナーをアクティブにする
            this.Activate();

            // 進行状況ダイアログを閉じる
            dialog.Close();

            // オーナーのフォームを有効に戻す
            this.Enabled = true;
        }

        private void LoadSettings()
        {
            global::L2Tools.L2l2.Properties.Settings settings = global::L2Tools.L2l2.Properties.Settings.Default;
            l2Directory.L2DirectoryPath = settings.L2Directory;
            l2Directory.RamdiskDirectoryPath = settings.RamdiskDirectory;

            l2Directory.Animations.Selected = settings.Animations;
            l2Directory.Maps.Selected = settings.Maps;
            l2Directory.Music.Selected = settings.Music;
            l2Directory.Sounds.Selected = settings.Animations;
            l2Directory.StaticMeshes.Selected = settings.StaticMeshes;
            l2Directory.System.Selected = settings.System;
            l2Directory.SysTextures.Selected = settings.SysTextures;
            l2Directory.Textures.Selected = settings.Textures;
            l2Directory.Voice.Selected = settings.Voice;

            l2Directory.IsAjust = settings.AjustSS;
            l2Directory.SsRepositoryPath = settings.SSDirectory;
        }

        private void SaveSettings()
        {
            global::L2Tools.L2l2.Properties.Settings settings = global::L2Tools.L2l2.Properties.Settings.Default;
            settings.L2Directory = l2Directory.L2DirectoryPath;
            settings.RamdiskDirectory = l2Directory.RamdiskDirectoryPath;

            settings.Animations = l2Directory.Animations.Selected;
            settings.Maps = l2Directory.Maps.Selected;
            settings.Music = l2Directory.Music.Selected;
            settings.Sounds = l2Directory.Sounds.Selected;
            settings.StaticMeshes = l2Directory.StaticMeshes.Selected;
            settings.System = l2Directory.System.Selected;
            settings.SysTextures = l2Directory.SysTextures.Selected;
            settings.Textures = l2Directory.Textures.Selected;
            settings.Voice = l2Directory.Voice.Selected;

            settings.AjustSS = l2Directory.IsAjust;
            settings.SSDirectory = l2Directory.SsRepositoryPath;

            settings.Save();
        }


        private void CountTotal()
        {
            l2Directory.Count();

            long totalSize = 0;

            if (l2Directory.Animations.Exists)
            {
                long size = l2Directory.Animations.Count().Size;
                totalSize += size;
                animationsLabel.Text = string.Format("{0:N0}", size) + Bytes;
            }
            else
            {
                animationsLabel.Text = MessageNotExists;
            }

            if (l2Directory.Maps.Exists)
            {
                long size = l2Directory.Maps.Count().Size;
                totalSize += size;
                mapsLabel.Text = string.Format("{0:N0}", size) + Bytes;
            }
            else
            {
                mapsLabel.Text = MessageNotExists;
            }

            if (l2Directory.Music.Exists)
            {
                long size = l2Directory.Music.Count().Size;
                totalSize += size;
                musicLabel.Text = string.Format("{0:N0}", size) + Bytes;
            }
            else
            {
                musicLabel.Text = MessageNotExists;
            }

            if (l2Directory.Sounds.Exists)
            {
                long size = l2Directory.Sounds.Count().Size;
                totalSize += size;
                soundsLabel.Text = string.Format("{0:N0}", size) + Bytes;
            }
            else
            {
                soundsLabel.Text = MessageNotExists;
            }

            if (l2Directory.StaticMeshes.Exists)
            {
                long size = l2Directory.StaticMeshes.Count().Size;
                totalSize += size;
                staticMeshesLabel.Text = string.Format("{0:N0}", size) + Bytes;
            }
            else
            {
                staticMeshesLabel.Text = MessageNotExists;
            }

            if (l2Directory.System.Exists)
            {
                long size = l2Directory.System.Count().Size;
                totalSize += size;
                systemLabel.Text = string.Format("{0:N0}", size) + Bytes;
            }
            else
            {
                systemLabel.Text = MessageNotExists;
            }

            if (l2Directory.SysTextures.Exists)
            {
                long size = l2Directory.SysTextures.Count().Size;
                totalSize += size;
                sysTexturesLabel.Text = string.Format("{0:N0}", size) + Bytes;
            }
            else
            {
                sysTexturesLabel.Text = MessageNotExists;
            }

            if (l2Directory.Textures.Exists)
            {
                long size = l2Directory.Textures.Count().Size;
                totalSize += size;
                texturesLabel.Text = string.Format("{0:N0}", size) + Bytes;
            }
            else
            {
                texturesLabel.Text = MessageNotExists;
            }

            if (l2Directory.Voice.Exists)
            {
                long size = l2Directory.Voice.Count().Size;
                totalSize += size;
                voiceLabel.Text = string.Format("{0:N0}", size) + Bytes;
            }
            else
            {
                voiceLabel.Text = MessageNotExists;
            }

            totalLabel.Text = string.Format("{0:N0}", totalSize) + Bytes;
        }

        private void CheckedChangedAnimations(object sender, EventArgs e)
        {
            l2Directory.Animations.Selected = checkBoxAnimations.Checked;
            CountTotal();
        }

        private void CheckedChangedMaps(object sender, EventArgs e)
        {
            l2Directory.Maps.Selected = checkBoxMaps.Checked;
            CountTotal();
        }

        private void CheckedChangedMusic(object sender, EventArgs e)
        {
            l2Directory.Music.Selected = checkBoxMusic.Checked;
            CountTotal();
        }

        private void CheckedChangedSounds(object sender, EventArgs e)
        {
            l2Directory.Sounds.Selected = checkBoxSounds.Checked;
            CountTotal();
        }

        private void CheckedChangedStaticMeshes(object sender, EventArgs e)
        {
            l2Directory.StaticMeshes.Selected = checkBoxStaticMeshes.Checked;
            CountTotal();
        }

        private void CheckedChangedSystem(object sender, EventArgs e)
        {
            l2Directory.System.Selected = checkBoxSystem.Checked;
            CountTotal();
        }

        private void CheckedChangedSystemTextures(object sender, EventArgs e)
        {
            l2Directory.SysTextures.Selected = checkBoxSysTextures.Checked;
            CountTotal();
        }

        private void CheckedChangedTextures(object sender, EventArgs e)
        {
            l2Directory.Textures.Selected = checkBoxTextures.Checked;
            CountTotal();
        }

        private void CheckedChangedVoice(object sender, EventArgs e)
        {
            l2Directory.Voice.Selected = checkBoxVoice.Checked;
            CountTotal();
        }

        private void ClickStart(object sender, EventArgs e)
        {
            Apply();
            l2Directory.Start();
            ChangeStatus(Status.Active);
        }

        private void ClickSave(object sender, EventArgs e)
        {
            SaveSettings();
        }

        private void ClicKTearDown(object sender, EventArgs e)
        {
            l2Directory.TearDown();
        }

        private void ClickStop(object sender, EventArgs e)
        {
            l2Directory.Stop();
            ChangeStatus(Status.Passive);
        }

        private void CheckedChangedAjustSS(object sender, EventArgs e)
        {
            l2Directory.IsAjust = checkBoxAjustSS.Checked;
            UpdateViewStatus();
        }

        private void ClickSelectSSRepository(object sender, EventArgs e)
        {
            //FolderBrowserDialogクラスのインスタンスを作成
            FolderBrowserDialog fbd = new FolderBrowserDialog();

            //上部に表示する説明テキストを指定する
            fbd.Description = "フォルダを指定してください。";
            //ルートフォルダを指定する
            //デフォルトでDesktop
            fbd.RootFolder = Environment.SpecialFolder.Desktop;
            //最初に選択するフォルダを指定する
            //RootFolder以下にあるフォルダである必要がある
            fbd.SelectedPath = ssFolder.Text;
            //ユーザーが新しいフォルダを作成できるようにする
            //デフォルトでTrue
            fbd.ShowNewFolderButton = true;

            //ダイアログを表示する
            if (fbd.ShowDialog(this) == DialogResult.OK)
            {
                if (!fbd.SelectedPath.Equals(l2Directory.SsRepositoryPath))
                {
                    l2Directory.SsRepositoryPath = fbd.SelectedPath;
                    UpdateViewStatus();
                }
            }
        }

        private void ClickExit(object sender, EventArgs e)
        {
            Application.Exit();
        }

        #endregion
    }
}
